package arith;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTreeNodeStream;

import arith.BasicArithmeticEquParser.evaluator_return;

public class ResponseCheckServer {
	public static final int PORT = 8889;
	
	public static void main(String args[]){
		new ResponseCheckServer().doIt();
	}
	
	public void doIt(){
		String userInput = "";
		try{
			ServerSocket ss = new ServerSocket(PORT);
			while(true){
				Socket sock = ss.accept();
				BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
				userInput = in.readLine();
				System.out.println(userInput);
				OutputStreamWriter out = new OutputStreamWriter(sock.getOutputStream());
				//ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
				BufferedWriter bw = new BufferedWriter(out);
				DecimalFormat df = new DecimalFormat("#.###");
				String sol = df.format(runTest(new Problem(userInput)).getSolution());
				System.out.println("\nSolution = "+sol);
				bw.write(sol+"\n");
				bw.flush();
				//Problem p = runTest(userInput);
				//System.out.println(p);
				//out.writeObject(p);
				
				//out.flush();
			}
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("Cannot connect to server");
		}
	}
	
	public Problem runTest(Problem prob) throws RecognitionException{
		//Parse prob's template and problem
		String equ = prob.getTemplate();
		CharStream charStream = new ANTLRStringStream(equ);
		BasicArithmeticEquLexer lexer = new BasicArithmeticEquLexer(charStream);
		TokenStream tokenStream = new CommonTokenStream(lexer);
		BasicArithmeticEquParser parser = new BasicArithmeticEquParser(tokenStream);
		evaluator_return evaluator = parser.evaluator();
		CommonTreeNodeStream nodeStream = new CommonTreeNodeStream(evaluator.tree);
		GrammarEvaluator walker = new GrammarEvaluator(nodeStream);
		
		//Prints out the tree
		//System.out.println(evaluator.tree.toStringTree());
		
		//The result of the expression
		Output result = walker.evaluator();
		
		if(result == null){
			System.out.println("result is null");
		}
	    if(result.id == 0){
	    	//Solution is a double
	    	prob.setProblem(result.nSolution.prob);
	    	prob.setSolution(result.nSolution.number);
	    }else if(result.id == 1){
	    	//Solution is a fraction
	    	prob.setProblem(result.fSolution.prob);
	    	prob.setSolution(result.fSolution);
	    }else if(result.id == 2){
	    	//Solution is an exponent
	    	prob.setProblem(result.eSolution.prob);
	    	prob.setSolution(result.eSolution);
	    }else if(result.id == 3){
	    	//Solution is a list of factors or a single int
	    	prob.setProblem(result.factorSolution.prob.getProblem());
	    	prob.setSolution(result.factorSolution.factors);
	    }else if(result.id == 4){
	    	//Solution is a string
	    	prob.setProblem(result.propSolution.prob.getProblem());
	    	prob.setSolution(result.propSolution.prob.stringSolution);
	    }else if(result.id == 5){
	    	//Solution is a polynomial
	    	prob.setProblem(result.polySolution.toString());
	    	prob.setSolution(result.polySolution);
	    }else{
	    	prob = null;
	    }
	    
	    //Print out the problem
	    System.out.println(prob.toString());
	    
	    //Print out the MathML of the problem
	    //System.out.println("MathML:" + makeImage(prob));
	    return prob;
	    
	}
	
}
